package bb.lanxing.lib.devices.ble.device;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import java.util.UUID;

import bb.lanxing.BuildConfig;
import bb.lanxing.lib.devices.api.SmartDevice;
import bb.lanxing.lib.devices.base.DeviceContext;
import bb.lanxing.lib.devices.base.SimpleBluetoothGattCallbackCompat;
import bb.lanxing.lib.devices.core.ble.AbsBleDevice;
import bb.lanxing.lib.devices.core.ble.SpecificationAttributes;
import bb.lanxing.lib.devices.core.dfu.ICDMDfuDevice;
import bb.lanxing.lib.devices.core.dfu.IDfuAdapter;
import bb.lanxing.lib.devices.core.dfu.IDfuDevice;
import bb.lanxing.lib.devices.core.provider.DataNotifier;
import bb.lanxing.lib.devices.heartrate01.HeartRate01Controller;
import bb.lanxing.lib.devices.heartrate01.HeartRate01WarningInfo;
import bb.lanxing.lib.devices.sprint.SimpleBleDeviceDfuAdapter;
import bb.lanxing.lib.devices.utils.ByteUtils;

public class HeartRate01Device extends AbsBleDevice implements HeartRate01Controller, IDfuDevice, ICDMDfuDevice {


    public static String ACTION_DEVICE_MODE_INFO = "action_device_mode_info";
    public static String EXTRA_HEART_RATE_MODE = "extra_heart_rate_mode";
    public static String ACTION_DEVICE_HEART_RATE_WARNING = "action_device_heart_rate_warning";
    public static String EXTRA_HEART_RATE_WARING = "extra_heart_rate_waring";
    public static final UUID BLE_HEART_RATE_SERVICE = UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb");
    public static final UUID BLE_HEART_RATE_MEASUREMENT = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb");


    private static final UUID BLE_SWITCH_HEART_RATE_SERVICE = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
    private static final UUID BLE_SWITCH_HEART_RATE_CMD = UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
    private static final UUID BLE_SWITCH_HEART_RATE_CMD_NOTIFY = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
    private boolean isSwitching;
    public static byte BLE_CMD_READ_SPORT_MODE = 1;
    public static byte BLE_CMD_WRITE_SPORT_MODE = 2;
    public static byte BLE_CMD_READ_HR_WARNING = 3;
    public static byte BLE_CMD_WRITE_HR_WARNING = 4;
    private BluetoothGattCharacteristic cmdNotifyService;
    private BluetoothGattCharacteristic cmdService;

    private IDfuAdapter mDfuAdapter;

    public HeartRate01Device(Context context, SmartDevice smartDevice) {
        super(smartDevice);
        init(context, smartDevice.getAddress(), new HeartateBluetoothGattCallback(this));
    }

    @SuppressLint("MissingPermission")
    @Override
    public void onServicesDiscovered() {
        super.onServicesDiscovered();

        BluetoothGattCharacteristic characteristic = mBluetoothGatt.getService(BLE_HEART_RATE_SERVICE).getCharacteristic(BLE_HEART_RATE_MEASUREMENT);
        mBluetoothGatt.readCharacteristic(characteristic);
        setCharacteristicNotification(characteristic, true);
        initSwitchServices();
        initBatteryNotify();
        IDfuAdapter iDfuAdapter = this.mDfuAdapter;
        if (iDfuAdapter != null) {
            iDfuAdapter.release();
            this.mDfuAdapter = null;
        }
    }

    private void initSwitchServices() {
        BluetoothGattService service = this.mBluetoothGatt.getService(BLE_SWITCH_HEART_RATE_SERVICE);
        this.cmdService = service.getCharacteristic(BLE_SWITCH_HEART_RATE_CMD);
        this.cmdNotifyService = service.getCharacteristic(BLE_SWITCH_HEART_RATE_CMD_NOTIFY);
        if (cmdNotifyService != null) {
            setCharacteristicNotification(cmdNotifyService, true);
        }
    }

    private void initBatteryNotify() {
        BluetoothGattService service = this.mBluetoothGatt.getService(BLE_BATTERY_SERVICE);
        if (service != null) {
            setCharacteristicNotification(service.getCharacteristic(BLE_BATTERY_CHARACTERISTIC), true);
        }
    }

    @SuppressLint("MissingPermission")
    @Override
    public boolean switchTo(int i) {
        if (this.cmdService == null || getBluetoothGatt() == null) {
            return false;
        }
        byte[] bytes = new byte[4];
        bytes[0] = (byte) (i & 255);
        bytes[2] = BLE_CMD_WRITE_SPORT_MODE;
        bytes[3] = BLE_CMD_WRITE_SPORT_MODE;
        this.cmdService.setValue(bytes);
        if (BuildConfig.DEBUG) {
            Log.e("heartRate01", "--------switchTo--" + ByteUtils.printlnByteArrayToUnsignHexString(bytes));
        }
        this.isSwitching = getBluetoothGatt().writeCharacteristic(this.cmdService);
        return this.isSwitching;
    }

    @SuppressLint("MissingPermission")
    @Override
    public void readCurrentMode() {
        if (this.cmdNotifyService == null || getBluetoothGatt() == null) {
            return;
        }
        byte[] bytes = new byte[4];
        bytes[2] = BLE_CMD_READ_SPORT_MODE;
        bytes[3] = BLE_CMD_READ_SPORT_MODE;
        this.cmdService.setValue(bytes);
        if (BuildConfig.DEBUG) {
            Log.e("heartRate01", "--------readCurrentMode--" + ByteUtils.printlnByteArrayToUnsignHexString(bytes));
        }
        getBluetoothGatt().writeCharacteristic(this.cmdService);
    }

    @SuppressLint("MissingPermission")
    @Override
    public void readHeartRateWaningInfo() {
        if (this.cmdNotifyService == null || getBluetoothGatt() == null) {
            return;
        }
        byte[] bytes = new byte[4];
        bytes[2] = BLE_CMD_READ_HR_WARNING;
        bytes[3] = BLE_CMD_READ_HR_WARNING;
//        this.cmdService.setValue(bytes);
        if (BuildConfig.DEBUG) {
            Log.e("heartRate01", "--------readHeartRateWaningInfo--" + ByteUtils.printlnByteArrayToUnsignHexString(bytes));
        }
//        getBluetoothGatt().writeCharacteristic(this.cmdService);
        enqueue(Request.newWriteRequest(cmdService, bytes));
    }

    @SuppressLint("MissingPermission")
    @Override
    public void writeHeartRateWaningInfo(HeartRate01WarningInfo warningInfo) {
        if (this.cmdNotifyService == null || getBluetoothGatt() == null) {
            return;
        }
        byte[] bytes = new byte[15];

        bytes[1] = warningInfo.highWarning;
        bytes[3] = (byte) warningInfo.highWarningValue;

        bytes[4] = warningInfo.lowWarning;
        bytes[6] = (byte) warningInfo.lowWarningValue;

        bytes[7] = (byte) warningInfo.zoomLevel1;
        bytes[8] = (byte) warningInfo.zoomLevel2;
        bytes[9] = (byte) warningInfo.zoomLevel3;
        bytes[10] = (byte) warningInfo.zoomLevel4;
        bytes[11] = (byte) warningInfo.zoomLevel5;
        bytes[12] = (byte) warningInfo.zoomLevel6;

        bytes[13] = BLE_CMD_WRITE_HR_WARNING;
        bytes[14] = BLE_CMD_WRITE_HR_WARNING;
        if (BuildConfig.DEBUG) {
            Log.e("heartRate01", "--------writeHeartRateWaningInfo--" + ByteUtils.printlnByteArrayToUnsignHexString(bytes));
        }
        this.cmdService.setValue(bytes);
        getBluetoothGatt().writeCharacteristic(this.cmdService);
    }

    @Override
    public IDfuAdapter getDfuAdapter() {
        if (this.mDfuAdapter == null) {
            this.mDfuAdapter = new SimpleBleDeviceDfuAdapter(this.mAppContext, this);
        }
        return this.mDfuAdapter;
    }

    @Override
    public boolean shouldAutoConnection() {
        return this.mDfuAdapter != null && !this.isSwitching;
    }

    @Override
    public BluetoothGattCharacteristic getCDMService() {
        return this.cmdService;
    }


    private static class HeartateBluetoothGattCallback extends SimpleBluetoothGattCallbackCompat<HeartRate01Device> {
        HeartateBluetoothGattCallback(HeartRate01Device standardHeartrateDevice) {
            super(standardHeartrateDevice);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic bluetoothGattCharacteristic) {
            int intValue;
            super.onCharacteristicChanged(bluetoothGatt, bluetoothGattCharacteristic);
            UUID uuid = bluetoothGattCharacteristic.getUuid();
            int type = this.mClientRef.getType();
            byte[] bytes1 = bluetoothGattCharacteristic.getValue();
            if (BuildConfig.DEBUG && bytes1.length > 0) {
                Log.e("heartRate01", "--------onCharacteristicChanged------uuid" + bluetoothGattCharacteristic.getUuid() + "  value=" + ByteUtils.printlnByteArrayToUnsignHexString(bytes1));
            }
            if (HeartRate01Device.BLE_HEART_RATE_MEASUREMENT.equals(uuid)) {
                if ((bluetoothGattCharacteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) & 1) == 0) {
                    intValue = bluetoothGattCharacteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1);
                } else {
                    intValue = bluetoothGattCharacteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 1);
                }
                DataNotifier.notifyHeartrateData(type, this.mClientRef.getAddress(), intValue);
            } else if (HeartRate01Device.BLE_SWITCH_HEART_RATE_CMD_NOTIFY.equals(uuid)) {
                byte[] bytes = bluetoothGattCharacteristic.getValue();
                if (bytes[0] == BLE_CMD_READ_SPORT_MODE && bytes[1] == BLE_CMD_READ_SPORT_MODE) {
                    setHeartMode(bytes[2]);
                } else if (bytes[0] == BLE_CMD_READ_HR_WARNING && bytes[1] == BLE_CMD_READ_HR_WARNING) {
                    setHeartWarning(bytes);
                }
            } else if (SpecificationAttributes.BLE_BATTERY_CHARACTERISTIC.equals(uuid)) {
                onReadBattery(bluetoothGattCharacteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0));
            }
        }

        public void setHeartMode(int mode) {
            Context applicationContext = DeviceContext.getApplicationContext();
            if (applicationContext == null) {
                return;
            }
            Intent intent = new Intent(ACTION_DEVICE_MODE_INFO);
            intent.putExtra(EXTRA_HEART_RATE_MODE, mode);
            intent.setPackage(applicationContext.getPackageName());
            applicationContext.sendBroadcast(intent);
        }

        public void setHeartWarning(byte[] value) {
            Context applicationContext = DeviceContext.getApplicationContext();
            if (applicationContext == null) {
                return;
            }
            HeartRate01WarningInfo info = new HeartRate01WarningInfo();
            info.highWarning = value[3];
            info.highWarningValue = ByteUtils.byte2Int(value[5]);

            info.lowWarning = value[6];
            info.lowWarningValue = ByteUtils.byte2Int(value[8]);

            info.zoomLevel1 = ByteUtils.byte2Int(value[9]);
            info.zoomLevel2 = ByteUtils.byte2Int(value[10]);
            info.zoomLevel3 = ByteUtils.byte2Int(value[11]);
            info.zoomLevel4 = ByteUtils.byte2Int(value[12]);
            info.zoomLevel5 = ByteUtils.byte2Int(value[13]);
            info.zoomLevel6 = ByteUtils.byte2Int(value[14]);

            Intent intent = new Intent(ACTION_DEVICE_HEART_RATE_WARNING);
            Bundle bundle = new Bundle();
            bundle.putSerializable(EXTRA_HEART_RATE_WARING, info);
            intent.putExtras(bundle);
            intent.setPackage(applicationContext.getPackageName());
            applicationContext.sendBroadcast(intent);
        }
    }
}
